#Standard imports
from random import random

#Panda specific imports for this module
from pandac.PandaModules import *

#To handle actors
from direct.actor import Actor

#To handle intervals
from direct.interval.IntervalGlobal import * 

#To handle particles

from direct.particles.Particles import Particles 
from direct.particles.ParticleEffect import ParticleEffect 
import math
import random
from panda3d.ai import *

#User imports
import globals #@UnusedImport
import bullet
from random import random

explosion = loader.loadModel("../data/lvl/level1/ene/LaserBurst1.egg")

class Explosion:
    def __init__(self,Position):
        self.node = render.attachNewNode("Explosion")
        self.explosion = explosion
        self.explosion.setLightOff()
        self.explosion.setScale(1.3,1.4,1.4)
        self.explosion.reparentTo(self.node)
        self.node.reparentTo(globals.PLAYER)
        taskMgr.doMethodLater(0.25,self.delete,'del')

    def delete(self,task):
        self.node.removeNode()
        del self
        return task.done

class EnemyMidi:
    def __init__(self):
        """Constructor
        We are not doing anything special here, only when we decide to init  
        right here we are only creating some variables     
        """
        self.model = None
        self.time = None
        self.startPos = None
        self.stageBelong = None
        self.points = []
        self.times = []
        self.sound = None
        self.pos = None
        self.dead = False
        self.scorePoints = 0
        self.actor = Actor.Actor();
        self.node = render.attachNewNode("Enemy")
        self.loop = False
        self.duration = 0
        self.endPos = None
        self.channel = 0
        self.note = 0
        self.volume = 0
        self.key = 0
        self.anim = None
        self.cNodePath = None
        self.type = "NORMAL"
        self.offset = 0.0
        self.snd = None
        self.coltype = ""
        self.colx = None
        self.coly = None
        self.colz = None
        self.opacity = 1.0

    def init(self):
        taskMgr.doMethodLater(self.time - self.offset, self._init, 'Start-Later-Enemy')

    def _init(self, task):
        if globals.NUMBERENEMIES >= globals.NUM_MAX_NUMBERENEMIES:
            del self
            return task.done


        globals.NUMBERENEMIES += 1

        if self.anim != "":
            self.actor.loadModel(self.model)
            self.actor.loadAnims({"Run":self.anim})
            self.actor.bindAnim('Run')
            self.actor.loop('Run')
            self.actor.setPlayRate(1.5 + (globals.RATE - 1), 'Run')
            self.actor.reparentTo(self.node)

        else:
            dummynode = loader.loadModel(self.model)
            dummynode.reparentTo(self.actor)
            self.actor.reparentTo(self.node)

            self.actor.setHpr(90,0,0)
            self.actor.setLightOff()
        

        self.actor.setColor(1.0,1.0,1.0,1.0)
        self.actor.setScale(1.0,1.0,1.0)

        self.cNode = CollisionNode('enemyMidiCol')
        self.cNode.setIntoCollideMask(BitMask32.bit(1))
        self.cNode.setFromCollideMask(BitMask32.allOff())

        if self.coltype == "BOX":
            self.cNode.addSolid(CollisionBox(Point3(0.0,0.0,0.0),self.colx,self.coly,self.colz))
        elif self.coltype == "SPHERE":
            self.cNode.addSolid(CollisionSphere(0, 0, 0.0, self.colx))
        elif self.coltype == "BOX_OFFSET":
            self.cNode.addSolid(CollisionBox(Point3(0.0,60.0,0.0),self.colx,self.coly,self.colz))

        self.cNodePath = self.actor.attachNewNode(self.cNode)
        self.duration = globals.TEMPO / 60
        self.startx = 4000
        
#        if self.type == "NORMAL":
#            if globals.ENEMYPOINT:
#                self.startPos = Point3(globals.ENEMYPOINT.getPos(render))
#            else:
#                self.startPos = Point3(self.startx,self.volume*math.cos(self.time),self.volume*math.sin(self.time))
#            int2 = LerpPosInterval(self.node,self.duration,Point3(globals.PlayerPosition.getX()-400,self.startPos.getY(),self.startPos.getZ()))
#
#        elif  self.type == "APPEAR":
#            self.startPos = Point3(self.startx,((self.pitch-64)*3)*math.cos(self.time),(self.pitch)*math.sin(self.time))
#            self.actor.setHpr(0,self.time*(self.volume/2.5),0)
#            int2 = Sequence(LerpPosInterval(self.node,self.duration,self.startPos),
#                            LerpScaleInterval(self.node, 0.1618, 0.0001, 1.0))
#
#        elif  self.type == "HITPOINT":
#            self.startPos = Point3(self.startx,50*math.cos(self.time),50*math.sin(self.time))
#            int2 = Sequence(LerpPosInterval(self.node,self.duration,globals.PlayerPosition+Point3(-400,0,0)),
#                            LerpScaleInterval(self.node, 0.01618, 0.0001, 1.0))
#
#        elif self.type == "VOL_DEPTH_APPEAR_SHOT":
#            self.startPos = Point3(400,50.0*math.cos(globals.THETA_SPIRAL),50*math.sin(globals.THETA_SPIRAL))
#            int2 = Sequence(LerpPosInterval(self.node,self.duration,self.startPos),LerpScaleInterval(self.node, 0.1618, 0.0001, 1.0))
#            taskMgr.doMethodLater(0,self._shoot, "shoot_from_enemy")
#            globals.THETA_SPIRAL += 0.5
#            print globals.THETA_SPIRAL
#
#        elif  self.type == "PITCH_SPIRAL_MOTION":
#            self.startPos = Point3(self.startx,0,0)
#            int2 = Sequence(LerpPosInterval(self.node,self.duration,Point3(globals.PlayerPosition.getX()-400,self.startPos.getY(),self.startPos.getZ())),
#                            LerpScaleInterval(self.node, 0.1618, 0.0001, 1.0))
#
#        elif self.type == "OFFSET_PLAYER_FOLLOWER":
#            if globals.ENEMYPOINT:
#                self.startPos = Point3(globals.ENEMYPOINT.getPos(render)+Point3(-190,0,0))
#            else:
#                self.startPos = Point3(self.startx,50*math.cos(self.time*(self.channel*0.05)),25*math.sin(self.time*(self.channel*0.05)))
#            int2 = LerpPosInterval(self.node,self.duration,Point3(globals.PlayerPosition.getX(),globals.PlayerPosition.getY(),globals.PlayerPosition.getZ()))
#
#        elif self.type == "PITCH_POSY_VOL_ROT":
#            self.startPos = Point3(self.startx,0,-120+(55-self.pitch)*20)
#            int2 = Sequence(LerpPosInterval(self.node,self.duration,Point3(globals.PlayerPosition.getX(),0,self.startPos.getZ())),(LerpPosInterval(self.node,self.duration/2,Point3(-self.startx/2,0,self.startPos.getZ()))))
#
#        elif self.type == "PITCH_ROT_VOL_POSX":
#            self.startPos = Point3(self.startx,0,0)
#            self.actor.setHpr(0,(400*math.sin(self.time)),0)
#            int2 = Sequence(LerpPosInterval(self.node,self.duration,Point3(globals.PlayerPosition.getX(),0,self.startPos.getZ())),(LerpPosInterval(self.node,self.duration/2,Point3(-self.startx/2,0,self.startPos.getZ()))))
#
        self.mySeq = Sequence()

        self.startPos = Point3(0,0,0)
        
        if self.type == "PASSROTATENOTE":
            self.startPos = Point3(self.startx,0,0)
            self.actor.setHpr(0,float(self.pitch-36)*15 ,0)
            int2 = LerpPosInterval(self.node,self.duration ,Point3(globals.PlayerPosition.getX(),0,self.startPos.getZ()))
            int3 = LerpPosInterval(self.node,self.duration , -self.startPos)
            self.mySeq.append(int2)
            self.mySeq.append(int3)

        self.parallel = Sequence(self.mySeq)
        
        if self.loop:
            self.parallel.loop()
        else:
            self.parallel.start()

        #Initial position set here.
        self.node.setPos(self.startPos)
        self.updateTask = taskMgr.add(self._update, 'Enemy-Update')
        return task.done


    def _shoot(self,task):
        bullet.BulletEnemy(Point3(globals.PlayerPosition.getX(),globals.PlayerPosition.getY(),globals.PlayerPosition.getZ()),self.startPos)
        return task.done

    def _update(self, task):
        dt = globalClock.getDt()
        if( dt > .20):
            return task.cont

        if  task.time > self.duration+0.5 or not self.parallel.isPlaying():
            self.node.removeNode()
            if self.dead == True:
                if self.sound != "" and self.snd:
                    self.snd.play()

            globals.LIFE -=1
            globals.NUMBERENEMIES -= 1
            del self
            return task.done
        return task.cont

    def die(self,player):
        player.life += 0.1
        exp = Explosion(self.node.getPos())
        self.dead = True
        self.parallel.finish()
